package com.gzsxy.esjy.service.netty.common.spel;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.SpelCompilerMode;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import javax.annotation.PostConstruct;

/**
 * spel解析通用
 * @author zhangxiaolong
 * @date 2022/7/11 9:36
 */
public abstract class AbstractSpelHandler {

	private SpelParserConfiguration configuration;
	
	private ExpressionParser parser;
	
	private BeanFactoryResolver resolver;
	
	private ParserContext parserContext;
	
	@Autowired
	private ApplicationContext applicationContext;
	
	@PostConstruct
	private void init() {
		configuration = new SpelParserConfiguration(SpelCompilerMode.MIXED, this.getClass().getClassLoader());
		parser = new SpelExpressionParser(configuration);
		resolver = new BeanFactoryResolver(applicationContext);
		
		
		parserContext = new ParserContext() {
			@Override
			public boolean isTemplate() {
				return true;
			}

			@Override
			public String getExpressionPrefix() {
				return "{";
			}

			@Override
			public String getExpressionSuffix() {
				return "}";
			}
		};
	}
	
	/**
	 * 解析spel，获取返回值
	 * @param joinPoint
	 * @param spel
	 * @return
	 */
	protected String parseSpel(ProceedingJoinPoint joinPoint, String spel) {
		//获取方法参数值
		Object[] args = joinPoint.getArgs();
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		//参数名
		String[] parameterNames = signature.getParameterNames();
		StandardEvaluationContext context = new StandardEvaluationContext();
		//赋值参数名：参数值
		for (int len = 0; len < parameterNames.length; len++) {
			context.setVariable(parameterNames[len], args[len]);
		}
		//追加自定义参数，特指本类
		context.setVariable("THIS", joinPoint.getTarget());
		context.setRootObject(applicationContext);
		context.setBeanResolver(resolver);
		Expression expression = parser.parseExpression(spel, parserContext);
		return expression.getValue(context, String.class);
	}
}
